package sjtu.ist.warehouse4ws.tool.parser;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.SAXException;

import sjtu.ist.warehouse4ws.action.file.FileAction;
import sjtu.ist.warehouse4ws.model.Domainmodel;
import sjtu.ist.warehouse4ws.model.Domainmodelattr;
import sjtu.ist.warehouse4ws.model.Domainmodelstate;
import sjtu.ist.warehouse4ws.model.Fileinfo;
import sjtu.ist.warehouse4ws.tool.ParseDomainModel;
import sjtu.ist.warehouse4ws.tool.file.ModelPackage;

public class DomainModelParser {
	private File file = null; // 模型文件
	private Document doc = null; // 文档对象
	private Domainmodel domainModel = null; // 领域模型实体
	private String modelId; // 模型ID
	private ArrayList<Domainmodelattr> attrList = null;// attr列表
	private ArrayList<Domainmodelstate> stateList = null;// state列表
	
	public DomainModelParser(File file) {
		this.file = file;
	}

	public DomainModelParser() {

	}

	/**
	 * 解析完整文件
	 */
	public void parse() {
		if (file == null) {
			System.out.println("未提供模型文件");
			return;
		}
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db = null;		
		try {
			db = dbf.newDocumentBuilder();
			doc = db.parse(file);
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		domainModel = new Domainmodel();		
		
		resolveModel();
		resolveDomianmodelattr();
		resolveState();
	}

	/**
	 * 解析节点
	 * 
	 * @param tagName
	 * @param doc
	 * @return
	 */
	public static String parseNode(String tagName, Document doc) {
		NodeList nodelist = doc.getElementsByTagName(tagName); // 获取该ID的标签
		Element node1 = (Element) nodelist.item(0); // 获取该ID标签的第一个Item
		NodeList nodelist2 = node1.getChildNodes(); // 获取该ID标签第一个Item里面的结点
		if (nodelist2.getLength() != 0) {
			String ttt = nodelist2.item(0).getNodeValue(); // 取值
			if (ttt.isEmpty()) {
				return null;
			} else {
				return ttt;
			}
		} else {
			return null;
		}
	}

	/**
	 * 初步解析模型文件，获得文档对象和模型实体
	 * 
	 * @return
	 */
	private void resolveModel() {
		// String
		// path="E:/Users/chenqidou/Desktop/models/371a5016-6d5e-4e9a-abcb-d7419733ac4c.xml";		
			
		modelId = parseNode("id", doc);
		String enName = parseNode("enName", doc);
		String cnName = parseNode("cnName", doc);
		String description = parseNode("description", doc);
		String type = parseNode("type", doc);
		String category = parseNode("category", doc);
		domainModel.setId(modelId);
		domainModel.setEnName(enName);
		domainModel.setCnName(cnName);
		domainModel.setDescription(description);
		domainModel.setType(type);
		domainModel.setCategory(category);
		// domainModel.setFileinfo(null);
	}

	private void resolveDomianmodelattr() {
		if (doc == null) {
			System.out.println("模型未被解析");
			return;
		}
		attrList = new ArrayList<Domainmodelattr>();
		Element root = doc.getDocumentElement();
		NodeList modelattrs = root
				.getElementsByTagName("domain_model_attribute");
		for (int i = 0; i < modelattrs.getLength(); i++) {
			Domainmodelattr domainmodelattr = new Domainmodelattr();
			Element modelattr = (Element) modelattrs.item(i);
			NodeList idList = modelattr.getElementsByTagName("id");
			String id = getNodeText(idList);
			System.out.println(id);
			domainmodelattr.setId(id);

			NodeList enNameList = modelattr.getElementsByTagName("enName");
			String enName = getNodeText(enNameList);

			domainmodelattr.setEnName(enName);

			NodeList cnNameList = modelattr.getElementsByTagName("cnName");
			String cnName = getNodeText(cnNameList);
			System.out.println(cnName);
			domainmodelattr.setCnName(cnName);

			NodeList descriptionList = modelattr
					.getElementsByTagName("description");
			String description = getNodeText(descriptionList);
			domainmodelattr.setDescription(description);

			NodeList cnTypeList = modelattr.getElementsByTagName("cnType");
			String cnType = getNodeText(cnTypeList);
			domainmodelattr.setCnType(cnType);

			NodeList enTypeList = modelattr.getElementsByTagName("enType");
			String enType = getNodeText(enTypeList);
			domainmodelattr.setEnType(enType);

			NodeList typeIdList = modelattr.getElementsByTagName("typeId");
			String typeId = getNodeText(typeIdList);
			domainmodelattr.setTypeId(typeId);

			NodeList maxValueList = modelattr.getElementsByTagName("maxValue");
			String maxValue = getNodeText(maxValueList);
			domainmodelattr.setMaxVal(maxValue);

			NodeList minValueList = modelattr.getElementsByTagName("minValue");
			String minValue = getNodeText(minValueList);
			domainmodelattr.setMinVal(minValue);

			NodeList readOnlyList = modelattr.getElementsByTagName("readOnly");
			String readOnly = getNodeText(readOnlyList);
			domainmodelattr.setReadOnly(Boolean.valueOf(readOnly));

			NodeList staticStateList = modelattr
					.getElementsByTagName("staticState");
			String staticState = getNodeText(staticStateList);
			domainmodelattr.setStaticstate(Boolean.valueOf(staticState));

			NodeList uniqueList = modelattr.getElementsByTagName("unique");
			String unique = getNodeText(uniqueList);
			domainmodelattr.setUni(Boolean.valueOf(unique));

			NodeList collectionTypeList = modelattr
					.getElementsByTagName("collectionType");
			String collectionType = getNodeText(collectionTypeList);
			domainmodelattr.setCollectionType(collectionType);

			NodeList defaultValueList = modelattr
					.getElementsByTagName("defaultValue");
			String defaultValue = getNodeText(defaultValueList);
			domainmodelattr.setDefaultValue(defaultValue);

			domainmodelattr.setDomainModelid(modelId);

			attrList.add(domainmodelattr);
		}
	}

	/**
	 * 解析模型文件，获得状态列表
	 * 
	 * @param path
	 * @return
	 */
	private void resolveState() {
		if (doc == null) {
			System.out.println("模型未被解析");
			return;
		}

		stateList = new ArrayList<Domainmodelstate>();
		Element root = doc.getDocumentElement();
		NodeList modelattrs = root.getElementsByTagName("domain_model_state");
		for (int i = 0; i < modelattrs.getLength(); i++) {
			Domainmodelstate Domainmodelstate = new Domainmodelstate();
			Element modelattr = (Element) modelattrs.item(i);
			NodeList idList = modelattr.getElementsByTagName("id");
			String id = getNodeText(idList);
			System.out.println(id);
			Domainmodelstate.setId(id);

			NodeList enNameList = modelattr.getElementsByTagName("enName");
			String enName = getNodeText(enNameList);
			Domainmodelstate.setEnName(enName);

			NodeList cnNameList = modelattr.getElementsByTagName("cnName");
			String cnName = getNodeText(cnNameList);
			System.out.println(cnName);
			Domainmodelstate.setCnName(cnName);

			NodeList descriptionList = modelattr
					.getElementsByTagName("description");
			String description = getNodeText(descriptionList);
			Domainmodelstate.setDescription(description);

			Domainmodelstate.setDomainModelid(modelId);

			stateList.add(Domainmodelstate);
		}
	}

	public static String getNodeText(NodeList node) {
		Element e = (Element) node.item(0);
		if (e == null) {
			return null;
		} // this judge is very important ,without it ,you will found nullpoint
			// Exception
		Text t = (Text) e.getFirstChild();
		if (t == null) {
			return null;
		}
		String str = t.getNodeValue();
		return str;
	}

	public static void main(String[] args) throws IOException, Exception {

		ParseDomainModel hel = new ParseDomainModel();
		String path = "E:/Users/chenqidou/Desktop/models/a1c38a8d-479e-4a44-ae95-024edda997c1.xml";
		hel.reserveModel(path);
		ArrayList<Domainmodelstate> hell = hel.reserveState(path);
//		for (int i = 0; i < hell.size(); i++) {
//			System.out.println(hell.get(i).getDomainModelid());
//			System.out.println(hell.get(i).getCnName());
//			System.out.println(hell.get(i).getEnName());
//		}
		// System.out.println(hel.reserveDomianmodelattr(path).get(0).getId());

	}

	public String checkDM(ModelPackage mp){ // get children path

		if(file==null){
			return null;
		}
		
		StringBuilder result=new StringBuilder();
		List<File> fileList = mp.domainFiles;//FileAction.getCheckConsistence();		
		NodeList nodelist = doc.getElementsByTagName("domain_model_attribute"); // get
																				// the
																				// child
																				// path
																				// from
																				// current
																				// xml
		for (int i = 0; i < nodelist.getLength(); i++) {
			Element dma = (Element) nodelist.item(i);
			NodeList str = dma.getElementsByTagName("typeId");
			Element paramElement = (Element) str.item(0);
			Text paramNode = (Text) paramElement.getFirstChild();
			String str1 = paramNode.getNodeValue();
			if (str1.length() > 2) { // 是个复杂类型的业务对象
				str1 += ".xml";
				int find = 0;
				for (File file : fileList) {
					if (file.getName().equals(str1)) {
						find = 1;
					}
				}
				if (find == 0){
					result.append("缺少业务对象文件：");
					result.append(str1);
					result.append(PackageParser.newline);
				}					
			}
		}
		return result.toString();

	}

	/**
	 * @param file
	 *            the file to set
	 */
	public void setFile(File file) {
		this.file = file;
	}

	/**
	 * @return the file
	 */
	public File getFile() {
		return file;
	}

	public Domainmodel getDomainModel() {
		return domainModel;
	}

	public String getModelId() {
		return modelId;
	}

	public ArrayList<Domainmodelattr> getAttrList() {
		return attrList;
	}

	public ArrayList<Domainmodelstate> getStateList() {
		return stateList;
	}
}
